from socket import *
import string
import cPickle
import time, threading,sys

pickle = cPickle

class NetServer:
    def __init__(self,addNetMessageFunc,port=None):
        self.addNetMessageFunc = addNetMessageFunc
        self.port = port
        self.goOnEvent = threading.Event()
        self.goOnEvent.set()

    def start(self):
        self.server_thread = NetChatThread(self.goOnEvent,self.addNetMessageFunc,port=self.port)
        self.server_thread.start()
        time.sleep(0.1)

    def isAlive(self):
        return self.server_thread.isAlive()

    def sendNetMessTo(self,addr,net_mess):
        #print "Sending1"
##        print net_mess

        self.server_thread.sendNetMessTo(addr,net_mess)
    def getMyAddr(self):
        return self.server_thread.getMyAddr()

    def close(self):
        self.goOnEvent.clear()
#        time.sleep(50)
        self.server_thread.close()
            

class NetChatThread(threading.Thread):
    def __init__(self,goOnEvent,addNetMessageFunc, port=None):
        self.goOnEvent = goOnEvent
        self.addNetMessage = addNetMessageFunc
        threading.Thread.__init__(self)
        self.port = port
        # create a listening socket
        self.rec_socket = socket(AF_INET, SOCK_DGRAM)
        # bind it to a port
        self.rec_socket.bind(("", self.port))
        self.rec_socket.settimeout(2.0)
        # create a sending socket
        self.snd_socket = socket(AF_INET, SOCK_DGRAM)
        # bind it to a port
        self.snd_socket.bind(("", self.port+1))
        self.t_lock = threading.Lock()
        
    def run(self):
        while self.goOnEvent.isSet():
            # read a package from the client
            try:
                data, (addr, port) = self.rec_socket.recvfrom(500)
            except timeout,e:
                continue
            if data == "quit":
                print "Got quit mess"
                break
            else:
                try:test_pick = pickle.loads(data)
                except pickle.PickleError,e:
                    print "Could not unpickle network data!"
                #test_pick.addr = (addr,port-1)
##                print "GOT: %s" %test_pick
                
                self.postNetMess(test_pick)
        self.rec_socket.close()
        print "Net Recv thread stopped"
        return

    def postNetMess(self,net_mess):
        self.addNetMessage(net_mess)

    def sendNetMessTo(self,addr,net_mess):
        objstr = pickle.dumps(net_mess,1)
        try:
            self.snd_socket.sendto("%s"%objstr, addr)
        except Exception,errmsg:
            sys.stderr.write("Error Cant send on socket:%s\n"%errmsg)

    def sendQuit(self):
        "Tell my server to quit so we get out of recv lock"
        try:
            self.snd_socket.sendto("quit", ("127.0.0.1",(self.rec_socket.getsockname())[1]) )
        except Exception,errmsg:
            sys.stderr.write("Error Cant send quit\n")
        self.goOnEvent.clear()
            
    def getMyAddr(self):
        return (gethostbyname(gethostname()), self.port)

    def close(self):
        print "Sending quit mess"
        self.sendQuit()
        self.snd_socket.close()
